package com.syh.jn.scm.service.impl.supplier.finance;

import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import cn.redscarf.commons.wrapper.expression.orderExpression.Order;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.downstream.entity.finance.DownCostBill;
import com.syh.jn.scm.domain.downstream.entity.finance.DownIncomeBill;
import com.syh.jn.scm.domain.downstream.entity.finance.DownPaymentBill;
import com.syh.jn.scm.domain.downstream.entity.logistics.DownLogisticsBill;
import com.syh.jn.scm.domain.downstream.event.DownCostBillEvent;
import com.syh.jn.scm.domain.downstream.event.DownIncomeBillEvent;
import com.syh.jn.scm.domain.downstream.event.DownLogisticsBillEvent;
import com.syh.jn.scm.domain.downstream.event.DownPaymentBillEvent;
import com.syh.jn.scm.domain.driver.entity.logistics.DriverLogisticsBill;
import com.syh.jn.scm.domain.driver.event.DriverLogisticsBillEvent;
import com.syh.jn.scm.domain.operation.entity.supplier.OperaSupplier;
import com.syh.jn.scm.domain.operation.event.supplier.OperaSupplierEvent;
import com.syh.jn.scm.domain.supplier.entity.finance.*;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseOrder;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseReturnOrder;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleOrder;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleReturnOrder;
import com.syh.jn.scm.domain.supplier.event.CostBillEvent;
import com.syh.jn.scm.domain.supplier.event.IncomeBillEvent;
import com.syh.jn.scm.domain.supplier.event.LogisticsBillEvent;
import com.syh.jn.scm.domain.supplier.event.PaymentBillEvent;
import com.syh.jn.scm.domain.supplier.event.finance.BusinessAccountRecordEvent;
import com.syh.jn.scm.domain.supplier.event.finance.OrderExpensesBillEvent;
import com.syh.jn.scm.domain.supplier.event.finance.ReceiptBillEvent;
import com.syh.jn.scm.domain.supplier.repository.finance.*;
import com.syh.jn.scm.domain.supplier.repository.logistics.LogisticsBillRepository;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseOrderRepository;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseReturnOrderRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleOrderRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleReturnOrderRepository;
import com.syh.jn.scm.domain.upstream.entity.finance.UpCostBill;
import com.syh.jn.scm.domain.upstream.entity.finance.UpIncomeBill;
import com.syh.jn.scm.domain.upstream.entity.finance.UpReceiptBill;
import com.syh.jn.scm.domain.upstream.entity.logistics.UpLogisticsBill;
import com.syh.jn.scm.domain.upstream.event.UpCostBillEvent;
import com.syh.jn.scm.domain.upstream.event.UpIncomeBillEvent;
import com.syh.jn.scm.domain.upstream.event.UpLogisticsBillEvent;
import com.syh.jn.scm.domain.upstream.event.UpReceiptBillEvent;
import com.syh.jn.scm.dto.supplier.finance.BusinessAccountRecordVo;
import com.syh.jn.scm.service.api.supplier.finance.BusinessAccountRecordService;
import com.syh.jn.scm.service.api.supplier.finance.enums.BusinessAccountRecordEnums;
import com.syh.jn.scm.service.api.supplier.finance.enums.OrderExpensesBillEnums;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import com.syh.jn.scm.service.api.supplier.purchase.enums.PurchaseOrderEnums;
import com.syh.jn.scm.service.api.supplier.purchase.enums.PurchaseReturnOrderEnums;
import com.syh.jn.scm.service.api.supplier.sale.enums.SaleOrderEnums;
import com.syh.jn.scm.service.api.supplier.sale.enums.SaleReturnOrderEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;

/**
 * 应收应付记录
 */
@Service
@Transactional
public class BusinessAccountRecordServiceImpl extends AbstractServiceImpl<Object, Object, BusinessAccountRecordVo, BusinessAccountRecord, Long> implements BusinessAccountRecordService {

    @Autowired
    private BusinessAccountRecordRepository recordRepository;
    @Autowired
    private LogisticsBillRepository logisticsBillRepository;
    @Autowired
    private CostBillRepository costBillRepository;
    @Autowired
    private IncomeBillRepository incomeBillRepository;
    @Autowired
    private PaymentBillRepository paymentBillRepository;
    @Autowired
    private ReceiptBillRepository receiptBillRepository;
    @Autowired
    private SaleOrderRepository saleOrderRepository;
    @Autowired
    private PurchaseReturnOrderRepository purchaseReturnOrderRepository;
    @Autowired
    private SaleReturnOrderRepository saleReturnOrderRepository;
    @Autowired
    private PurchaseOrderRepository purchaseOrderRepository;


    @Override
    protected AggregateRepository getAggregateRepository() {
        return recordRepository;
    }

    /**
     * 纠正数据使用 纠正应收付记录中的累计汇总
     *
     * @param customerType 客户类型
     */
    @Override
    public void recalculationAccountRecordSummary(Short customerType) {
        ExtAssert.isTrue(customerType != null, "customerType 不能为 null");
        recordRepository.recalculationAccountRecordSummary(customerType);
    }

    /**
     * 纠正数据使用 纠正应收付记录中的优惠金额
     */
    @Override
    public void recalculationAccountRecordDiscount() {
        recordRepository.recalculationAccountRecordDiscount();
    }

    /**
     * 纠正数据使用 纠正订单未生成应收付记录
     */
    @Override
    public void correctAccountRecord() {
        recordRepository.correctAccountRecord();
    }

    /**
     * 服务商费用单双方确认 纳入应收付记录
     *
     * @param bill
     */
    @DomainEventHandle(CostBillEvent.COST_BILL_STATE_CONFIRM)
    protected void handleCostBillConfirmEvent(CostBill bill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 下游收入单双方确认 纳入应收付记录
     *
     * @param bill
     */
    @DomainEventHandle(DownIncomeBillEvent.DOWNSTREAM_INCOME_BILL_STATE_CONFIRM)
    protected void handleDownIncomeBillConfirmEvent(DownIncomeBill bill) {
        CostBill costBill = costBillRepository.getById(bill.getId());
        this.handleCostBillConfirmEvent(costBill);
    }

    /**
     * 上游收入单双方确认 纳入应收付记录
     *
     * @param bill
     */
    @DomainEventHandle(UpIncomeBillEvent.UP_INCOME_BILL_STATE_CONFIRM)
    protected void handleUpIncomeBillConfirmEvent(UpIncomeBill bill) {
        CostBill costBill = costBillRepository.getById(bill.getId());
        this.handleCostBillConfirmEvent(costBill);
    }

    /**
     * 服务商费用单取消确认 纳入应收付记录
     *
     * @param bill
     */
    @DomainEventHandle(CostBillEvent.COST_BILL_STATE_UN_CONFIRM)
    protected void handleCostBillUnConfirmEvent(CostBill bill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(bill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 下游收入单据取消确认 纳入应收付记录
     *
     * @param bill
     */
    @DomainEventHandle(DownIncomeBillEvent.DOWNSTREAM_INCOME_BILL_STATE_UN_CONFIRM)
    protected void handlePaymentBillCancelEvent(DownIncomeBill bill) {
        CostBill costBill = costBillRepository.getById(bill.getId());
        this.handleCostBillUnConfirmEvent(costBill);
    }

    /**
     * 上游收入单据取消确认 纳入应收付记录
     */
    @DomainEventHandle(UpIncomeBillEvent.UP_INCOME_BILL_STATE_UN_CONFIRM)
    protected void handleUpIncomeBillRemoveEvent(UpIncomeBill bill) {
        CostBill costBill = costBillRepository.getById(bill.getId());
        this.handleCostBillUnConfirmEvent(costBill);
    }

    /**
     * 服务商收入单据双方确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(IncomeBillEvent.INCOME_BILL_STATE_CONFIRM)
    protected void handleIncomeBillConfirmEvent(IncomeBill bill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 下游费用单据双方确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(DownCostBillEvent.DOWNSTREAM_COST_BILL_STATE_CONFIRM)
    protected void handleDownCostBillConfirmEvent(DownCostBill bill) {
        IncomeBill incomeBill = incomeBillRepository.getById(bill.getId());
        this.handleIncomeBillConfirmEvent(incomeBill);
    }

    /**
     * 上游费用单据双方确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(UpCostBillEvent.UP_COST_BILL_STATE_CONFIRM)
    protected void handleUpCostBillEvent(UpCostBill bill) {
        IncomeBill incomeBill = incomeBillRepository.getById(bill.getId());
        this.handleIncomeBillConfirmEvent(incomeBill);
    }

    /**
     * 服务商收入单据（删除对应生成应收付记录）取消
     *
     * @param incomeBill
     */
    @DomainEventHandle(IncomeBillEvent.INCOME_BILL_STATE_UN_CONFIRM)
    protected void handleIncomeBillUnConfirmEvent(IncomeBill incomeBill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(incomeBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 下游费用单据取消确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(DownCostBillEvent.DOWNSTREAM_COST_BILL_UN_CONFIRM)
    protected void handleIncomeBillStateUnConfirmEvent(DownCostBill bill) {
        IncomeBill incomeBill = incomeBillRepository.getById(bill.getId());
        this.handleIncomeBillUnConfirmEvent(incomeBill);
    }

    /**
     * 上游费用单据取消确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(UpCostBillEvent.UP_COST_BILL_STATE_UN_CONFIRM)
    protected void handleUpCostBillUnConfirmEvent(UpCostBill bill) {
        IncomeBill incomeBill = incomeBillRepository.getById(bill.getId());
        this.handleIncomeBillUnConfirmEvent(incomeBill);
    }

    /**
     * 监听物流单发货
     */
    @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_DELIVERY)
    protected void handleLogisticsBillDeliveryEvent(LogisticsBill bill) {
        if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
                || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus())) {
            //检查订单是否存在优惠金额，当存在优惠金额时创建优惠金额应收付记录
            this.checkDiscount(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
            this.publicEvent(BusinessAccountRecordEvent.buildBusinessAccountRecordCheckDiscountAfterEvent(new Object[]{bill}));
            //新增应收付历史记录
            BusinessAccountRecord record = new BusinessAccountRecord(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
            this.addNewBusinessAccountRecord(record);
        }
    }

    /**
     * 监听司机端物流单发货
     */
    @DomainEventHandle(DriverLogisticsBillEvent.DRIVER_LOGISTICS_BILL_DELIVERY)
    protected void handleLogisticsBillDeliveryEvent(DriverLogisticsBill driverLogisticsBill) {
        LogisticsBill bill = logisticsBillRepository.getById(driverLogisticsBill.getId());
        this.handleLogisticsBillDeliveryEvent(bill);
    }

    /**
     * 监听物流单收货
     */
    @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_COLLECTED)
    protected void handleLogisticsBillCollectedEvent(LogisticsBill bill) {
        //采购、销售退货单收货 生成供应商、客户应收付记录
        if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.PURCHASE.getStatus())
                || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_SALE.getStatus())) {
            //检查订单是否存在优惠金额，当存在优惠金额时创建优惠金额应收付记录
            this.checkDiscount(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
            this.publicEvent(BusinessAccountRecordEvent.buildBusinessAccountRecordCheckDiscountAfterEvent(new Object[]{bill}));
            //新增应收付历史记录
            BusinessAccountRecord record = new BusinessAccountRecord(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
            this.addNewBusinessAccountRecord(record);
        }
      //销售、采购退回货单收货 生成物流应收付记录
      if ((bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
              || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus()))
              && bill.getLogisticsCompanyId() != null) {
        //直采直销的物流单不生成应收付记录
        if (bill.getSubjectBillId() != null) {
          return;
        }
        BusinessAccountRecord businessAccountRecord = new BusinessAccountRecord(bill, Short.valueOf("1"),bill.getLogisticsCompanyId());
        //新增应收付历史记录
        this.addNewBusinessAccountRecord(businessAccountRecord);
      }

    }

    /**
     * 监听司机物流单收货
     */
    @DomainEventHandle(DriverLogisticsBillEvent.DRIVER_LOGISTICS_BILL_COLLECTED)
    protected void handleLogisticsBillCollectedEvent(DriverLogisticsBill driverLogisticsBill) {
        LogisticsBill bill = logisticsBillRepository.getById(driverLogisticsBill.getId());
        this.handleLogisticsBillCollectedEvent(bill);
    }

    /**
     * 监听物流单取消发货
     */
    @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_CANCELLED)
    protected void handleLogisticsBillCancelledEvent(LogisticsBill bill,LogisticsBill oldBill) {
        if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
                || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus())) {
            //检查订单是否存在优惠金额，当存在优惠金额时创建优惠金额应收付记录
            this.publicEvent(BusinessAccountRecordEvent.buildBusinessAccountRecordCheckDiscountBeforeEvent(new Object[]{bill}));
            this.checkDiscount(oldBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
            //新增应收付历史记录
            BusinessAccountRecord record = new BusinessAccountRecord(oldBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
            this.addNewBusinessAccountRecord(record);
        }
    }

    /**
     * 监听物流单取消签收
     *
     * @param bill
     */
    @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_UN_RECEIVED)
    protected void handleLogisticsBillUnReceivedEvent(LogisticsBill bill, LogisticsBill oldBill) {
        //采购、销售退货单收货 生成供应商、客户应收付记录
        if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.PURCHASE.getStatus())
                || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_SALE.getStatus())) {
            //检查订单是否存在优惠金额，当存在优惠金额时创建优惠金额应收付记录
            this.publicEvent(BusinessAccountRecordEvent.buildBusinessAccountRecordCheckDiscountBeforeEvent(new Object[]{bill}));
            this.checkDiscount(oldBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
            //新增应收付历史记录
            BusinessAccountRecord record = new BusinessAccountRecord(oldBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
            this.addNewBusinessAccountRecord(record);
        }
    }
  /**
   * 监听客户物流收货 (生成物流应收付记录)
   */
  @DomainEventHandle(DownLogisticsBillEvent.DOWN_LOGISTICS_BILL_COLLECTED)
  protected void handleLogisticsBillCollectedEvent(DownLogisticsBill downLogisticsBill) {
    LogisticsBill logisticsBill = logisticsBillRepository.getById(downLogisticsBill.getId());
    this.handleLogisticsBillCollectedEvent(logisticsBill);
  }

  /**
   * 监听客户物流取消收货 (生成物流应收付记录)
   */
  @DomainEventHandle(DownLogisticsBillEvent.DOWN_LOGISTICS_BILL_UN_RECEIVED)
  protected void handleLogisticsBillUnReceivedEvent(DownLogisticsBill downLogisticsBill,DownLogisticsBill oldBill) {
    LogisticsBill bill = logisticsBillRepository.getById(oldBill.getId());
    //设置签收时间为旧单签收时间（因为bill从数据库获取 无法保证是更新前还是更新后数据 所有手动设置旧单签收时间）
    bill.setStorageTimestamp(oldBill.getStorageTimestamp());
    //销售、采购退回货单收货 生成物流应收付记录
    if ((bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
            || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus()))
            && bill.getLogisticsCompanyId() != null) {
      //直采直销的物流单不生成应收付记录
      if (bill.getSubjectBillId() != null) {
        return;
      }
      BusinessAccountRecord businessAccountRecord = new BusinessAccountRecord(bill, Short.valueOf("2"),bill.getLogisticsCompanyId());
      //新增应收付历史记录
      this.addNewBusinessAccountRecord(businessAccountRecord);
    }
  }

  /**
   * 监听供应商物流收货 (生成物流应收付记录)
   */
  @DomainEventHandle(UpLogisticsBillEvent.UP_LOGISTICS_BILL_COLLECTED)
  protected void handleLogisticsBillCollectedEvent(UpLogisticsBill upLogisticsBill) {
    LogisticsBill logisticsBill = logisticsBillRepository.getById(upLogisticsBill.getId());
    this.handleLogisticsBillCollectedEvent(logisticsBill);
  }
  /**
   * 监听供应商物流取消收货 (生成物流应收付记录)
   */
  @DomainEventHandle(UpLogisticsBillEvent.UP_LOGISTICS_BILL_UN_RECEIVED)
  protected void handleLogisticsBillUnReceivedEvent(UpLogisticsBill upLogisticsBill, UpLogisticsBill oldBill) {
    LogisticsBill bill = logisticsBillRepository.getById(oldBill.getId());
    //设置签收时间为旧单签收时间（因为bill从数据库获取 无法保证是更新前还是更新后数据 所有手动设置旧单签收时间）
    bill.setStorageTimestamp(oldBill.getStorageTimestamp());
    //销售、采购退回货单收货 生成物流应收付记录
    if ((bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
            || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus()))
            && bill.getLogisticsCompanyId() != null) {
      BusinessAccountRecord businessAccountRecord = new BusinessAccountRecord(bill, Short.valueOf("2"),bill.getLogisticsCompanyId());
      //新增应收付历史记录
      this.addNewBusinessAccountRecord(businessAccountRecord);
    }
  }

  /**
   * 监听订单费用表确认（生成订单费用应收付记录）
   * @param orderExpensesBill
   */
  @DomainEventHandle(OrderExpensesBillEvent.ORDER_EXPENSES_BILL_CONFIRM)
  protected void handleOrderExpensesBillConfirmEvent(OrderExpensesBill orderExpensesBill) {
    //默认没有纳入订单总额的费用项 不生成应收付记录
    boolean unRecord = true;
    for (OrderExpensesBillItem item: orderExpensesBill.getItems()) {
      //如果有纳入订单总额的费用项 则生成应收付记录
      if (item.getIncludeTotalAmount().equals(OrderExpensesBillEnums.IncludeTotalAmount.INCLUDE.getStatus())) {
        unRecord = false;
        break;
      }
    }
    if (unRecord) {
      return ;
    }
    BusinessAccountRecord businessAccountRecord = new BusinessAccountRecord(orderExpensesBill,Short.valueOf("1"));
    //新增应收付历史记录
    this.addNewBusinessAccountRecord(businessAccountRecord);
  }
  /**
   * 监听订单费用表取消确认（生成订单费用应收付记录）
   * @param orderExpensesBill
   * @param oldBill
   */
  @DomainEventHandle(OrderExpensesBillEvent.ORDER_EXPENSES_BILL_CANCEL)
  protected void handleOrderExpensesBillCancelEvent(OrderExpensesBill orderExpensesBill, OrderExpensesBill oldBill) {
    //默认没有纳入订单总额的费用项 不生成应收付记录
    boolean unRecord = true;
    for (OrderExpensesBillItem item: orderExpensesBill.getItems()) {
      //如果有纳入订单总额的费用项 则生成应收付记录
      if (item.getIncludeTotalAmount().equals(OrderExpensesBillEnums.IncludeTotalAmount.INCLUDE.getStatus())) {
        unRecord = false;
        break;
      }
    }
    if (unRecord) {
      return ;
    }
    BusinessAccountRecord businessAccountRecord = new BusinessAccountRecord(oldBill,Short.valueOf("2"));
    //新增应收付历史记录
    this.addNewBusinessAccountRecord(businessAccountRecord);
  }

    /**
     * 服务商付款单据双方确认（生成应收付记录）
     */
    @DomainEventHandle(PaymentBillEvent.PAYMENT_BILL_LOCK)
    protected void handlePaymentBillLockEvent(PaymentBill paymentBill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(paymentBill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 上游收款(服务商付款)单据双方确认（生成应收付记录）
     */
    @DomainEventHandle(UpReceiptBillEvent.UP_RECEIPT_BILL_LOCK)
    protected void handleUpReceiptBillEvent(UpReceiptBill bill) {
        PaymentBill paymentBill = paymentBillRepository.getById(bill.getId());
        this.handlePaymentBillLockEvent(paymentBill);
    }

    /**
     * 服务商付款单据取消确认（生成应收付记录）
     *
     * @param paymentBill
     */
    @DomainEventHandle(PaymentBillEvent.PAYMENT_BILL_UNLOCK)
    protected void handlePaymentBillUnLockEvent(PaymentBill paymentBill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(paymentBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 上游收款(服务商付款)取消确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(UpReceiptBillEvent.UP_RECEIPT_BILL_UNLOCK)
    protected void handlePaymentBillCancelEvent(UpReceiptBill bill) {
        PaymentBill paymentBill = paymentBillRepository.getById(bill.getId());
        this.handlePaymentBillUnLockEvent(paymentBill);
    }

    /**
     * 服务商收款单据双方确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(ReceiptBillEvent.RECEIPT_BILL_LOCK)
    protected void handleReceiptBillLockEvent(ReceiptBill bill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(bill, BusinessAccountRecordEnums.DataType.NORMAL.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 服务商收款单据取消确认（生成应收付记录）
     *
     * @param receiptBill
     */
    @DomainEventHandle(ReceiptBillEvent.RECEIPT_BILL_UNLOCK)
    protected void handleReceiptBillUnLockEvent(ReceiptBill receiptBill) {
        //新增应收付历史记录
        BusinessAccountRecord record = new BusinessAccountRecord(receiptBill, BusinessAccountRecordEnums.DataType.ROLL_BACK.getStatus());
        this.addNewBusinessAccountRecord(record);
    }

    /**
     * 下游付款(服务商收款)单据双方确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(DownPaymentBillEvent.DOWN_PAYMENT_BILL_LOCK)
    protected void handleDownPaymentBillEvent(DownPaymentBill bill) {
        ReceiptBill receiptBill = receiptBillRepository.getById(bill.getId());
        this.handleReceiptBillLockEvent(receiptBill);
    }

    /**
     * 下游付款(服务商收款)单据取消确认（生成应收付记录）
     *
     * @param bill
     */
    @DomainEventHandle(DownPaymentBillEvent.DOWN_PAYMENT_BILL_UNLOCK)
    protected void handleDownPaymentBillUnLockEvent(DownPaymentBill bill) {
        ReceiptBill receiptBill = receiptBillRepository.getById(bill.getId());
        this.handleReceiptBillUnLockEvent(receiptBill);
    }

    /**
     * 新增应收付历史记录
     *
     * @param record
     */
    protected void addNewBusinessAccountRecord(BusinessAccountRecord record) {
        //找到当前往来单位最新插入的数据
        BigDecimal newCreateTimeSummaryBalance = this.findNewCreateTimeSummaryBalance(record.getBusinessEntityId(), record.getCustomerType(), record.getCustomerId());

        BigDecimal summaryBalance = null;
        //更新汇总余额
    /*if (record.getRePayAmount() == null) {
      summaryBalance = newCreateTimeSummaryBalance.add(record.getChangeAmount());
    } else {
      summaryBalance = newCreateTimeSummaryBalance.subtract(record.getRePayAmount());
    }*/

        summaryBalance = newCreateTimeSummaryBalance.add(record.getChangeAmount());
        record.setSummaryBalance(summaryBalance);
        //添加到数据库
        recordRepository.add(record);
        this.publicEvent(BusinessAccountRecordEvent.buildBusinessAccountRecoredCreatedEvent(new Object[]{record}));
    }

    /**
     * 查找对应往来单位的最新汇总余额
     *
     * @param businessEntityId
     * @param customerType
     * @param customerId
     * @return
     */
    private BigDecimal findNewCreateTimeSummaryBalance(Long businessEntityId, Short customerType, Long customerId) {
        //查找出当前服务商的应收付汇总信息
        Wrapper we = Wrapper.build();
        we.append(Restrictions.eq("businessEntityId", businessEntityId));
        we.append(Restrictions.eq("customerId", customerId));
        we.append(Restrictions.eq("customerType", customerType));
//        we.order(Order.desc("createTimeStamp"));
        List<BusinessAccountRecord> recordList = recordRepository.getList(we);

        if (recordList.size() > 0 && recordList != null) {
            //找到当前客户最新插入的数据
            BusinessAccountRecord newCreateTimeRecord = recordList.stream()
                    .max(Comparator.comparing(record -> record.getCreateTimeStamp() == null?0:record.getCreateTimeStamp()))
                    .get();
            //初始化值
            if (newCreateTimeRecord.getSummaryBalance() == null) {
                newCreateTimeRecord.setSummaryBalance(BigDecimal.ZERO);
            }

            return newCreateTimeRecord.getSummaryBalance();
        } else {
            return BigDecimal.ZERO;
        }
    }


  private void checkDiscount(LogisticsBill bill, Short dataType) {
    switch (bill.getOrderType()) {
      case 0://销售订单
        SaleOrder sale = saleOrderRepository.getById(bill.getOrderId());
        if (sale.getDeliveryState().equals(SaleOrderEnums.DeliveryState.LOGISTICS_UN_DELIVERY.getStatus())
                && sale.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
          BusinessAccountRecord record = new BusinessAccountRecord();
          record.discount(bill, dataType);
          this.addNewBusinessAccountRecord(record);
        }
        break;
      case 3://采购退货订单
        PurchaseReturnOrder purRet = purchaseReturnOrderRepository.getById(bill.getOrderId());
        if (purRet.getDeliveryState().equals(PurchaseReturnOrderEnums.DeliveryState.LOGISTICS_UN_DELIVERY.getStatus())
                && purRet.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
          BusinessAccountRecord record = new BusinessAccountRecord();
          record.discount(bill, dataType);
          this.addNewBusinessAccountRecord(record);
        }
        break;
      case 1://销售退货订单
        SaleReturnOrder saleRet = saleReturnOrderRepository.getById(bill.getOrderId());
        if (saleRet.getCollectState().equals(SaleReturnOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus())
                && saleRet.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
          BusinessAccountRecord record = new BusinessAccountRecord();
          record.discount(bill, dataType);
          this.addNewBusinessAccountRecord(record);
        }
        break;
      case 2://采购订单
        PurchaseOrder pur = purchaseOrderRepository.getById(bill.getOrderId());
        if (pur.getCollectState().equals(PurchaseOrderEnums.CollectState.LOGISTICS_UN_COLLECT.getStatus())
                && pur.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
          BusinessAccountRecord record = new BusinessAccountRecord();
          record.discount(bill, dataType);
          this.addNewBusinessAccountRecord(record);
        }
        break;
    }
  }

  /**
   * 消费者：监听服务商反开账（删除所有该服务商的应收付记录）
   */
  @DomainEventHandle(OperaSupplierEvent.SUPPLIER_REVERSAL_ACCOUNT)
  protected void handleSupplierReversalAccount(OperaSupplier supplier) {
    this.recordRepository.deleteByBusinessEntityId(supplier.getId());
  }
}
